/**
 * @file logger.h
 * @brief 基于 syslog 的 log 封装。
 */
#ifndef LOGGER_H_74147F5D_ED37_4ABF_9E0A_F1ED53C60FFF_
#define LOGGER_H_74147F5D_ED37_4ABF_9E0A_F1ED53C60FFF_

#include <syslog.h>
#include <stdio.h>
#ifdef THREAD_MT
#include <pthread.h>
#endif// THREAD_MT

#if __WORDSIZE == 64
#define INT64_FMT "%ld"
#define UINT64_FMT "%lu"
#else
#define INT64_FMT "%lld"
#define UINT64_FMT "%llu"
#endif

/**
 * @def LOG_OPEN( ident, option, facility )
 * 初始化 log 系统。
 * @remarks 参数 ident，option，facility 含义与 openlog 相同。
 */
#define LOG_OPEN( ident, option, facility ) ::openlog( ident, option, facility );
/**
 * @def LOG_CLOSE()
 * 关闭 log 系统。
 */
#define LOG_CLOSE ::closelog();

/**
 * @def DEBUG_LOG( fmt, ... )
 * 按 fmt 指定格式输出调试日志。
 */

/**
 * @def MEMBER_DEBUG_LOG( fmt, ... )
 * 按 fmt 指定格式输出调试日志，用于非静态类成员方法、操作符方法里。
 */

/**
 * @def LOG( level, fmt, ... )
 * 按 level 指定级别和 fmt 指定格式输出日志。
 * @remarks 参数 level 的设定与 syslog 相同。
 */

/**
 * @def MEMBER_LOG( level, fmt, ... )
 * 按 level 指定级别 fmt 指定格式输出日志，用于非静态类成员方法、操作符方法里。
 * @remarks 参数 level 的设定与 syslog 相同。
 */

#ifdef THREAD_MT
#define LOG_LOCATION_FORMAT_ "<%s, %s, line %d, thread %p>"
#define LOG_LOCATION_ARGS_ __FILE__, __FUNCTION__, __LINE__, ( void* )pthread_self()
#define MEMBER_LOG_LOCATION_FORMAT_  "<%s, %s, line %d, thread %p, this=%p>"
#define MEMBER_LOG_LOCATION_ARGS_ __FILE__, __FUNCTION__, __LINE__, ( void* )pthread_self(), this
#else
#define LOG_LOCATION_FORMAT_ "<%s, %s, line %d>"
#define LOG_LOCATION_ARGS_ __FILE__, __FUNCTION__, __LINE__
#define MEMBER_LOG_LOCATION_FORMAT_ "<%s, %s, line %d, this=%p>"
#define MEMBER_LOG_LOCATION_ARGS_ __FILE__, __FUNCTION__, __LINE__, this
#endif// THREAD_MT

#ifdef DEBUG_LOG_ON
#ifdef THREAD_MT
#define DEBUG_LOG_LOCATION_FORMAT_ "<%s, line %d, thread %p>"
#define DEBUG_LOG_LOCATION_ARGS_ __FILE__, __LINE__, ( void* )pthread_self()
#define MEMBER_DEBUG_LOG_LOCATION_FORMAT_ "<%s, line %d, thread %p, this=%p>"
#define MEMBER_DEBUG_LOG_LOCATION_ARGS_ __FILE__, __LINE__, ( void* )pthread_self(), this
#else
#define DEBUG_LOG_LOCATION_FORMAT_ "<%s, line %d>"
#define DEBUG_LOG_LOCATION_ARGS_ __FILE__, __LINE__
#define MEMBER_DEBUG_LOG_LOCATION_FORMAT_ "<%s, line %d, this=%p>"
#define MEMBER_DEBUG_LOG_LOCATION_ARGS_ __FILE__, __LINE__, this
#endif// THREAD_MT
#define DEBUG_LOG( fmt, ... ) ::syslog( LOG_DEBUG, DEBUG_LOG_LOCATION_FORMAT_ fmt, DEBUG_LOG_LOCATION_ARGS_, ## __VA_ARGS__ );
#define MEMBER_DEBUG_LOG( fmt, ... ) ::syslog( LOG_DEBUG, MEMBER_DEBUG_LOG_LOCATION_FORMAT_ fmt, MEMBER_DEBUG_LOG_LOCATION_ARGS_, ## __VA_ARGS__ );
#else
#define DEBUG_LOG_
#define DEBUG_LOG( fmt, ... ) DEBUG_LOG_
#define MEMBER_DEBUG_LOG( fmr, ... ) DEBUG_LOG_
#endif//#ifdef DEBUG_LOG_ON

#define LOG_( level, ... ) ::syslog( level, ## __VA_ARGS__ );
#define PRINT_( f, ... ) ::fprintf( f, ## __VA_ARGS__ );

#define LOG( level, fmt, ... ) \
LOG_( level, LOG_LOCATION_FORMAT_ fmt, LOG_LOCATION_ARGS_, ## __VA_ARGS__ );\
if ( level != LOG_DEBUG )\
{\
    DEBUG_LOG( fmt, ## __VA_ARGS__ );\
}

#define MEMBER_LOG( level, fmt, ... ) \
LOG_( level, MEMBER_LOG_LOCATION_FORMAT_ fmt, MEMBER_LOG_LOCATION_ARGS_, ## __VA_ARGS__ );\
if ( level != LOG_DEBUG )\
{\
    DEBUG_LOG( fmt, ## __VA_ARGS__ );\
}

#define PURE_LOG LOG_

#endif// LOGGER_H_74147F5D_ED37_4ABF_9E0A_F1ED53C60FFF_
